// Copyright 2017 Mobvoi Inc. All Rights Reserved.
// Author: congfu@mobvoi.com (Cong Fu)

#ifndef SDK_UTILS_OS_SUPPORT_H_
#define SDK_UTILS_OS_SUPPORT_H_

#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

#if defined(SCO_CP_ACCEL)
#include "hal_location.h"
#define MOB_CP_TEXT_SRAM_LOC CP_TEXT_SRAM_LOC
#else
#define MOB_CP_TEXT_SRAM_LOC
#endif

#ifdef __BES_CORTEX_M4__

#if defined(ENABLE_EE172_PIPELINE) || defined(ENABLE_OONTZ_PIPELINE) || \
    defined(ENABLE_TONLY_PIPELINE) || defined(ENABLE_AOJIE_PIPELINE) || \
    defined(ENABLE_NOTHING_PIPELINE) || defined(ENABLE_1000SHORES_PIPELINE)
#define SUPPORT_FRAME_LEN_15MS
#elif defined(ENABLE_EE145_PIPELINE) || defined(ENABLE_OPPO_PIPELINE) || \
      defined(ENABLE_EE178_PIPELINE) || defined(ENABLE_PATOZON_PIPELINE) || \
      defined(ENABLE_NOISE_PIPELINE) || defined(ENABLE_AA428_PIPELINE) || \
      defined(ENABLE_EE175_PIPELINE) || defined(ENABLE_AP022_PIPELINE)
#define SUPPORT_FRAME_LEN_7_5MS
#elif defined(ENABLE_SMART_LINK_PIPELINE)
#define SUPPORT_FRAME_LEN_4MS
#endif
#define SUPPORT_SAMPLE_RATE_8K
#define SUPPORT_KISS_FFT

#elif defined(__QCC5121__)

#define SUPPORT_FRAME_LEN_4MS
#define SUPPORT_KISS_FFT

#elif defined(__CEVA__)

#define SUPPORT_FRAME_LEN_4MS
#define SUPPORT_CEVA_FFT
//#define SUPPORT_KISS_FFT

#elif defined(__CEVAX__)
#ifdef ENABLE_YULIANG_DOA_PIPELINE
#define SUPPORT_FRAME_LEN_16MS
#define SUPPORT_HANN_WINDOW
#define SUPPORT_VORBIS_WINDOW
#define SUPPORT_SAMPLE_RATE_16K
#define SUPPORT_KISS_FFT
#else
#define SUPPORT_SAMPLE_RATE_8K
#define SUPPORT_SAMPLE_RATE_16K
#define SUPPORT_KISS_FFT
#define SUPPORT_SAMPLE_RATE_48K
#define SUPPORT_VORBIS_WINDOW
#define SUPPORT_FRAME_LEN_8MS
#define SUPPORT_FRAME_LEN_10MS
#define SUPPORT_HANN_WINDOW
#define SUPPORT_FRAME_LEN_7_5MS
#endif
#elif defined(__CEVABX__)
#define SUPPORT_SAMPLE_RATE_16K
#define SUPPORT_KISS_FFT
#define SUPPORT_HANN_WINDOW
#define SUPPORT_FRAME_LEN_7_5MS
#define SUPPORT_SAMPLE_RATE_48K
//#define SUPPORT_FRAME_LEN_7_5MS
//#define SUPPORT_SAMPLE_RATE_44K1
//#define SUPPORT_HANN_WINDOW
//#define SUPPORT_FRAME_LEN_5MS
//#define SUPPORT_SAMPLE_RATE_32K
//#define SUPPORT_FRAME_LEN_30MS
#elif defined(__SHENLEI__)
#define SUPPORT_FRAME_LEN_10MS
#define SUPPORT_SAMPLE_RATE_16K
#define SUPPORT_KISS_FFT
#define SUPPORT_SAMPLE_RATE_48K
#define SUPPORT_GENERATE_WINDOW
#define SUPPORT_VORBIS_WINDOW
#define SUPPORT_FRAME_LEN_8MS
#elif defined(__THREAD_X__)
#define SUPPORT_FRAME_LEN_10MS  // insta
#define SUPPORT_FRAME_LEN_8MS
#define SUPPORT_FRAME_LEN_4MS   // insta
#define SUPPORT_SAMPLE_RATE_48K // insta oneR
#define SUPPORT_NE10_FFT
#define SUPPORT_KISS_FFT
#define SUPPORT_HANN_WINDOW
#define SUPPORT_VORBIS_WINDOW
#elif defined(__RISC_V__)
#define SUPPORT_FRAME_LEN_7_5MS
#define SUPPORT_KISS_FFT

#elif defined(__XTENSA__)
#define SUPPORT_FRAME_LEN_10MS
#define SUPPORT_KISS_FFT
#if defined(ENABLE_HUKE_PIPELINE)
#define SUPPORT_VORBIS_WINDOW
#define SUPPORT_FRAME_LEN_8MS
#define SUPPORT_SAMPLE_RATE_48K
#endif
#elif defined(__ASDK__)
#define SUPPORT_FRAME_LEN_10MS
#define SUPPORT_KISS_FFT

#elif defined(_MSC_VER)
#define SUPPORT_FRAME_LEN_10MS
#define SUPPORT_KISS_FFT

#else  // not bes/qcc

#define SUPPORT_SAMPLE_RATE_8K
#define SUPPORT_SAMPLE_RATE_16K
#define SUPPORT_SAMPLE_RATE_48K
#define SUPPORT_SAMPLE_RATE_32K
#define SUPPORT_SAMPLE_RATE_44K1
#define SUPPORT_FRAME_LEN_4MS
#define SUPPORT_FRAME_LEN_5MS
#define SUPPORT_FRAME_LEN_10MS
#define SUPPORT_FRAME_LEN_16MS

#if defined(ENABLE_EE172_PIPELINE) || defined(ENABLE_OONTZ_PIPELINE) || \
    defined(ENABLE_TONLY_PIPELINE) || defined(ENABLE_AOJIE_PIPELINE) || \
    defined(ENABLE_NOTHING_PIPELINE) || defined(ENABLE_1000SHORES_PIPELINE)
#define SUPPORT_FRAME_LEN_15MS
#elif defined(ENABLE_EE145_PIPELINE) || defined(ENABLE_OPPO_PIPELINE) || \
      defined(ENABLE_EE178_PIPELINE) || defined(ENABLE_PATOZON_PIPELINE) || \
      defined(ENABLE_NOISE_PIPELINE) || defined(ENABLE_AA428_PIPELINE) || \
      defined(ENABLE_EE175_PIPELINE)
#define SUPPORT_FRAME_LEN_7_5MS
#else
#define SUPPORT_FRAME_LEN_7_5MS
#define SUPPORT_FRAME_LEN_15MS
#define SUPPORT_FRAME_LEN_8MS
#define SUPPORT_FRAME_LEN_16MS
#endif

#define SUPPORT_VORBIS_WINDOW
#define SUPPORT_HANN_WINDOW
#define SUPPORT_KISS_FFT
#ifndef MOBVOI_FIXED_POINT
#define SUPPORT_GENERATE_WINDOW
#define SUPPORT_NAIVE_FFT
#define SUPPORT_NE10_FFT
#endif
#define LARGE_MEMORY_MODE
#define SUPPORT_FRAME_LEN_30MS

#endif

#if defined(ENABLE_PUBLIC_ADDRESS_PIPELINE)
#define SUPPORT_LOWDELAY_WINDOW
#endif

#ifndef MOBVOI_FIXED_POINT
#if defined(ENABLE_STM32_PIPELINE)   || defined(ENABLE_EE172_PIPELINE) || \
    defined(ENABLE_TONLY_PIPELINE)   || defined(ENABLE_SMART_LINK_PIPELINE) || \
    defined(ENABLE_OONTZ_PIPELINE)   || defined(ENABLE_AOJIE_PIPELINE) || \
    defined(ENABLE_EE145_PIPELINE)   || defined(ENABLE_NOISE_PIPELINE) || \
    defined(ENABLE_EE175_PIPELINE)   || defined(ENABLE_OPPO_PIPELINE)  || \
    defined(ENABLE_NOTHING_PIPELINE) || defined(ENABLE_AA428_PIPELINE) || \
    defined(ENABLE_1000SHORES_PIPELINE)
// used by downlink NR/FFT
#define SUPPORT_CORTEX_M4_FFT
#endif

#if defined(ENABLE_STM32_PIPELINE)
#define SUPPORT_FULL_CORTEX_M4_FFT
#endif
#endif

#if !defined(ENABLE_INSTA360_PIPELINE) && !defined(ENABLE_STM32_PIPELINE) && \
    !defined(ENABLE_EE172_PIPELINE) && !defined(ENABLE_TONLY_PIPELINE) && \
    !defined(ENABLE_SMART_LINK_PIPELINE) && !defined(ENABLE_OONTZ_PIPELINE) && \
    !defined(ENABLE_EE178_PIPELINE) && !defined(ENABLE_EE145_PIPELINE) && \
    !defined(ENABLE_PATOZON_PIPELINE) && !defined(ENABLE_AOJIE_PIPELINE) && \
    !defined(ENABLE_OPPO_PIPELINE) && !defined(ENABLE_NOISE_PIPELINE) && \
    !defined(ENABLE_EE175_PIPELINE) && !defined(ENABLE_TELINK_PIPELINE) && \
    !defined(ENABLE_CEVA_PIPELINE) && !defined(ENABLE_RECORDER_PEN_PIPELINE) && \
    !defined(ENABLE_NOTHING_PIPELINE) && !defined(ENABLE_AA428_PIPELINE) && \
    !defined(ENABLE_1BK3288_PIPELINE) && !defined(ENABLE_2BK3288_PIPELINE) && \
    !defined(ENABLE_1000SHORES_PIPELINE) && !defined(ENABLE_WIRELESS_MIC_PIPELINE) && \
    !defined(ENABLE_INSTA_WEBCAM_PIPELINE) && !defined(ENABLE_BK3288_WIRELESS_PIPELINE) && \
    !defined(ENABLE_2BK3288_WIRELESS_PIPELINE) && !defined(ENABLE_CRNLSTM_DENOISE_PIPELINE) && \
    !defined(ENABLE_TIMELC_DENOISE_PIPELINE) && !defined(ENABLE_RNNOISE_PIPELINE) && \
    !defined(ENABLE_INTERPHONE_PIPELINE) && !defined(ENABLE_VIVO_PIPELINE) && \
    !defined(ENABLE_YIYUAN_PIPELINE) && !defined(ENABLE_KGEBAO_PIPELINE) && \
    !defined(ENABLE_TAIXINGBANG_PIPELINE) && !defined(ENABLE_DSPG_PIPELINE) && \
    !defined(ENABLE_CLASSIFY_PIPELINE) && !defined(ENABLE_HUKE_PIPELINE) && \
    !defined(ENABLE_QUECTEL_KWS_PIPELINE) && !defined(ENABLE_TWOSTREAM_PIPELINE) && \
    !defined(ENABLE_TWOSTREAM_PIPELINE) && !defined(ENABLE_WORLDELITE_KWS_PIPELINE) && \
    !defined(ENABLE_JINPENG_PIPELINE) && !defined(ENABLE_XINGGU_PIPELINE) && \
    !defined(ENABLE_CRNGRU_TINY_Q_PIPELINE) && !defined(ENABLE_QUECTEL_PIPELINE) && \
    !defined(ENABLE_BK7256_KWS_PIPELINE) && !defined(ENABLE_HONGKETE_PIPELINE) && \
    !defined(ENABLE_ZUOYEBANG_VAD_PIPELINE) && !defined(ENABLE_YILUO_PIPELINE) && \
    !defined(ENABLE_SHENLEI_PIPELINE) && !defined(ENABLE_YULIANG_DOA_PIPELINE) && \
    !defined(ENABLE_TCNLSTM_PIPELINE) && !defined(ENABLE_AP022_PIPELINE)
#define SUPPORT_CONFIG_FILE
#define SUPPORT_FULL_AEC
#endif

#if defined(__QCC5121__)
#include "audio_log/audio_log.h"
#include "pmalloc/pl_malloc.h"
#include "pmalloc/pl_malloc_preference.h"
#define MOB_MEM_DM1     MALLOC_PREFERENCE_DM1
#define MOB_MEM_DM2     MALLOC_PREFERENCE_DM2
#define MOB_MEM_NONE    MALLOC_PREFERENCE_NONE
#define MOB_MEM_FAST    MALLOC_PREFERENCE_FAST
#ifdef RUNNING_ON_KALSIM
#define MOB_MEM_SHARED  MALLOC_PREFERENCE_NONE
#else
#define MOB_MEM_SHARED  MALLOC_PREFERENCE_SHARED
#endif
#define MOB_MEM_EXT     MALLOC_PREFERENCE_EXTERNAL
#define MOB_MEM_SYS     MALLOC_PREFERENCE_SYSTEM
#endif  // __QCC5121__

#include "sdk/utils/mob_types.h"

#ifdef __THREAD_X__
#include "sdk/utils/amba_utils.h"
#endif

#ifdef __CEVA__
#include "asm-tl3.h"
#include "asm-tl3-72.h"
#include "CEVA_common.h"
#endif

#if defined(__CEVAX__) || defined(__CEVABX__)
#include "third_party/V2.0.2_RTL1_4/include/ceva_dsp_lib.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if defined(__BES_CORTEX_M4__) || defined(__arm__) || defined(__i386__) || \
    defined(__QCC5121__) || defined(__XTENSA__) || defined(__RISC_V__) || \
    defined(__CEVA__) || defined(__ASDK__) || defined(__CEVAX__)
typedef uint32 mob_ptr;
#else
typedef uint64 mob_ptr;
#endif

#if defined(MOBVOI_FIXED_POINT)
typedef int32 mob_float;
#define FIXED_SATURATION
#elif defined(MOBVOI_FIXED_POINT_16BIT)
typedef int16 mob_float;
#define FIXED_SATURATION
#else
typedef float mob_float;
#endif  // MOBVOI_FIXED_POINT

#if !defined(_MVSILICON_) && !defined(__XTENSA__) && !defined(__THREAD_X__) \
 && !defined(__QCC5121__) && !defined(__STM32__) && !defined(__BES_CORTEX_M4__) \
 && !defined(__RISC_V__) && !defined(_MSC_VER) && !defined(__CEVA__) \
 && !defined(__ASDK__) && !defined(__CEVAX__) && !defined(__QUECTEL_ASR_KERNEL__) \
 && !defined(__CEVABX__)
#include <memory.h>
#define MOBVOI_MULTI_THREAD

#ifndef NDEBUG
#define LOG_FILE_INFO
#endif

#else

#include <string.h>
#define MOBVOI_DSP_CHIPSET

#endif

#ifdef ENABLE_GPROF
void monstartup(char const*);
void moncleanup();
#endif

#if defined(ENABLE_STM32_PIPELINE) || defined(ENABLE_INSTA360_PIPELINE) || \
    defined(ENABLE_EE172_PIPELINE) || defined(ENABLE_TONLY_PIPELINE) || \
    defined(ENABLE_SMART_LINK_PIPELINE) || defined(ENABLE_OONTZ_PIPELINE) || \
    defined(ENABLE_EE178_PIPELINE) || defined(ENABLE_EE145_PIPELINE) || \
    defined(ENABLE_PATOZON_PIPELINE) || defined(ENABLE_AOJIE_PIPELINE)|| \
    defined(ENABLE_OPPO_PIPELINE) || defined(ENABLE_NOISE_PIPELINE) || \
    defined(ENABLE_EE175_PIPELINE) || defined(ENABLE_TELINK_PIPELINE) || \
    defined(ENABLE_RECORDER_PEN_PIPELINE) || defined(ENABLE_NOTHING_PIPELINE) || \
    defined(ENABLE_AA428_PIPELINE) || defined(ENABLE_1BK3288_PIPELINE) || \
    defined(ENABLE_1000SHORES_PIPELINE) || defined(ENABLE_BK3288_WIRELESS_PIPELINE) || \
    defined(ENABLE_2BK3288_WIRELESS_PIPELINE) || defined(ENABLE_HUKE_PIPELINE) || \
    defined(ENABLE_JINPENG_PIPELINE) || defined(ENABLE_XINGGU_PIPELINE) || \
    defined(ENABLE_ZUOYEBANG_VAD_PIPELINE) || defined(ENABLE_YILUO_PIPELINE) || \
    defined(ENABLE_YULIANG_DOA_PIPELINE) || defined(ENABLE_TCNLSTM_PIPELINE) || \
    defined(ENABLE_AP022_PIPELINE)
#define ENABLE_DATA_CACHE_OPTIMIZ
#endif

// #define NR_DEBUG

//#define BIT_WIDE_24BITS

#ifdef BIT_WIDE_24BITS
#define Q_MOBVOI_WINDOWS Q23
#define Q_HANN_WINDOWS Q23
#define Q_FFT_TWIDDLES Q23
#define Q_FFT_SUPER_TWIDDLES Q23
#define Q_MULTI_FIXED_FREQ_SIGNAL_BF  Q30
#define Q_MULTI_FIXED_FREQ_POWER_BF   Q29
#define Q_MULTI_FIXED_TAR_NOTAR_COEF_BF  Q22
#define Q_kMaxVectorGain_BF Q21
#define Q_NR_WIENER  Q23
#define Q_WINDOWS_FBANK Q23
#define Q_FFT_TWIDDLES_FBANK Q23
#define Q_FFT_SUPER_TWIDDLES_FBANK Q23
#else
#if defined(ENABLE_PUBLIC_ADDRESS_PIPELINE)
#define Q_MOBVOI_WINDOWS Q30
#else
#define Q_MOBVOI_WINDOWS Q31
#endif
#define Q_HANN_WINDOWS Q31
#define Q_FFT_TWIDDLES Q30
#define Q_FFT_SUPER_TWIDDLES Q31
#define Q_MULTI_FIXED_FREQ_SIGNAL_BF  Q30
#define Q_MULTI_FIXED_FREQ_POWER_BF   Q29
#define Q_MULTI_FIXED_TAR_NOTAR_COEF_BF  Q30
#define Q_kMaxVectorGain_BF Q29
#define Q_NR_WIENER  Q31
#define Q_WINDOWS_FBANK Q31
#define Q_FFT_TWIDDLES_FBANK Q31
#define Q_FFT_SUPER_TWIDDLES_FBANK Q31
#endif

#define kPI               (3.14159265358979323846f)
#define kSmallFloatValue  (1e-6f)
#define kFloatNearZero    (1e-8f)
#define kFloatNearZero_inv (1e8f)

#define kWavHeaderLen     (44)
#define kScalingFactor    (32768.0f) // (1 << 15)
#define kScalingFactor_Inv (0.000030517578125f)

// 1e-8f 687.19476736
#define kFixedNearZero    (687)
#define kFixedNearZeroQ   (36)

// #define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ?
//                       __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)

#ifdef DISABLE_DEBUG
#define mobvoi_warning(...)
#define mobvoi_info(...)
#define mobvoi_fatal(...)
#define mob_printf(...)

#elif defined(__THREAD_X__)
#if defined(ENABLE_INSTA_LOG)
#define mobvoi_warning(fmt, ...) \
    InsUtil_Log_Print(INSUTIL_LOG_WARNING, fmt, ##__VA_ARGS__)
#define mobvoi_info(fmt, ...) \
     InsUtil_Log_Print(INSUTIL_LOG_INFO, fmt, ##__VA_ARGS__)
#define mobvoi_fatal(fmt, ...) \
    InsUtil_Log_Print(INSUTIL_LOG_ERR, fmt, ##__VA_ARGS__); \
    *(volatile int*) 0 = 0;
#define mob_printf(fmt, ...) \
    InsUtil_Log_Print(INSUTIL_LOG_INFO, fmt, ##__VA_ARGS__)
#else
#define mobvoi_warning(...)
#define mobvoi_info(...)
#define mobvoi_fatal(...)
#define mob_printf(...)
#endif

#elif defined(__QCC5121__)
// Return count - 1
#define INTERNAL_ARG_COUNT_PRIVATE(\
     _0,  _1,  _2,  _3,  _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define ARG_COUNT(...) INTERNAL_ARG_COUNT_PRIVATE(0, __VA_ARGS__, \
     9, 8, 7, 6, 5, 4, 3,  2,  1,  0,  0)
#define L0_DBG_MSG0 L0_DBG_MSG
#define A(x) L0_DBG_MSG##x
#define LOG_FUNC_TMP(x)     A(x)
#define mobvoi_info(...)    LOG_FUNC_TMP(ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
#define mobvoi_warning(...) mobvoi_info(__VA_ARGS__)
#define mobvoi_fatal(...)   mobvoi_info(__VA_ARGS__)
#define mob_printf(...)     mobvoi_info(__VA_ARGS__)

#elif defined(__STM32__)
uint32_t am_util_stdio_printf(const char *pcFmt, ...);
#define mobvoi_warning am_util_stdio_printf
#define mobvoi_info    am_util_stdio_printf
#define mobvoi_fatal   am_util_stdio_printf
#define mob_printf     am_util_stdio_printf

// #elif defined(ENABLE_SMART_LINK_PIPELINE) && defined(__BES_CORTEX_M4__)
// #include <stdbool.h>
// extern int xprintf(bool block, const char *format, ...);
// #define mobvoi_warning(...) xprintf(true, __VA_ARGS__)
// #define mobvoi_info(...)    xprintf(true, __VA_ARGS__)
// #define mobvoi_fatal(...)   xprintf(true, __VA_ARGS__)
// #define mob_printf(...)     xprintf(true, __VA_ARGS__)

#elif defined(ENABLE_BES_LOG)
int hal_trace_printf(const char *pcFmt, ...);
#define mobvoi_warning hal_trace_printf
#define mobvoi_info    hal_trace_printf
#define mobvoi_fatal   hal_trace_printf
#define mob_printf     hal_trace_printf

#elif defined(ENABLE_BES_LOG_NEW)
int hal_trace_printf(uint32, const char *pcFmt, ...);
#define mobvoi_warning(...) hal_trace_printf(1, __VA_ARGS__)
#define mobvoi_info(...)    hal_trace_printf(2, __VA_ARGS__)
#define mobvoi_fatal(...)   hal_trace_printf(0, __VA_ARGS__)
#define mob_printf(...)     hal_trace_printf(2, __VA_ARGS__)
#elif defined(__SHENLEI__) && defined(_MSC_VER)
void print_log(char type, const char* file, int line, const char* fmt, ...);

#define mobvoi_warning(fmt, ...) \
    print_log('W', __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define mobvoi_info(fmt, ...) \
    print_log('I', __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define mobvoi_fatal(fmt, ...) \
    print_log('E', __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
   *(volatile int*) 0 = 0;
#define mob_printf(...) printf(__VA_ARGS__)
#elif defined(_MSC_VER)
#define mobvoi_warning printf
#define mobvoi_info    printf
#define mobvoi_fatal   printf
#define mob_printf     printf

#elif defined(XTENSA_HIFI4)
// #define CONFIG_DSP_ENABLE_UART_PRINTF
#if defined(CONFIG_DSP_ENABLE_UART_PRINTF)
int DspUartPrintf(char *fmt, ...);
#define printf DspUartPrintf
#elif defined(CONFIG_DSP_ENABLE_HOST_PRINTF)
void DspHostPrintf(char *fmt, ...);
#define printf DspHostPrintf
#else
#define printf(...)
#endif

#define mobvoi_warning printf
#define mobvoi_info    printf
#define mobvoi_fatal   printf
#define mob_printf     printf

#elif defined(__RISC_V__)
#ifdef ENABLE_BK7256_KWS_PIPELIINE
int bk_printf(const char *fmt, ...);
#define mobvoi_warning(...) do { bk_printf(__VA_ARGS__); bk_printf("\n"); } while (0)
#define mobvoi_info(...)    do { bk_printf(__VA_ARGS__); bk_printf("\n"); } while (0)
#define mobvoi_fatal(...)   do { bk_printf(__VA_ARGS__); bk_printf("\n"); } while (0)
#define mob_printf(...)     do { bk_printf(__VA_ARGS__); bk_printf("\n"); } while (0)
#else
#define mobvoi_warning(...) do { printf(__VA_ARGS__); printf("\n"); } while (0)
#define mobvoi_info(...)    do { printf(__VA_ARGS__); printf("\n"); } while (0)
#define mobvoi_fatal(...)   do { printf(__VA_ARGS__); printf("\n"); } while (0)
#define mob_printf(...)     do { printf(__VA_ARGS__); printf("\n"); } while (0)
#endif
#elif defined(__CEVAX__)
#define ENABLE_BK_LOG
#if defined(ENABLE_BK_LOG)
int bk_printf(const char *fmt, ...);
#define mobvoi_warning(...) do { bk_printf(__VA_ARGS__); bk_printf("\n"); } while (0)
#define mobvoi_info(...)    do { bk_printf(__VA_ARGS__); bk_printf("\n"); } while (0)
#define mobvoi_fatal(...)   do { bk_printf(__VA_ARGS__); bk_printf("\n"); } while (0)
#define mob_printf(...)     do { bk_printf(__VA_ARGS__); bk_printf("\n"); } while (0)
#else
#define mobvoi_warning(...)
#define mobvoi_info(...)
#define mobvoi_fatal(...)
#define mob_printf(...)
#endif
#elif defined(__CEVABX__)
int mobvoi_printf(const char *fmt, ...);
#define mobvoi_warning(...) do { mobvoi_printf(__VA_ARGS__); mobvoi_printf("\n"); } while (0)
#define mobvoi_info(...)    do { mobvoi_printf(__VA_ARGS__); mobvoi_printf("\n"); } while (0)
#define mobvoi_fatal(...)   do { mobvoi_printf(__VA_ARGS__); mobvoi_printf("\n"); } while (0)
#define mob_printf(...)     do { mobvoi_printf(__VA_ARGS__); mobvoi_printf("\n"); } while (0)
#elif defined(__CEVA__)
void FW_printf(const char *format, ...);
#define mobvoi_warning(...) do { FW_printf(__VA_ARGS__); FW_printf("\n"); } while (0)
#define mobvoi_info(...)    do { FW_printf(__VA_ARGS__); FW_printf("\n"); } while (0)
#define mobvoi_fatal(...)   do { FW_printf(__VA_ARGS__); FW_printf("\n"); } while (0)
#define mob_printf(...)     do { FW_printf(__VA_ARGS__); } while (0)

#elif defined(XTENSA_HIFI3)
void print_to_uart(const char *format, ...);
#define mobvoi_warning(str, ...) do { print_to_uart("MOBVOI[W]: "str, ##__VA_ARGS__); print_to_uart("\n"); } while (0)
#define mobvoi_info(str, ...) do { print_to_uart("MOBVOI[I]: "str, ##__VA_ARGS__); print_to_uart("\n"); } while (0)
#define mobvoi_fatal(str, ...) do { print_to_uart("MOBVOI[F]: "str, ##__VA_ARGS__); print_to_uart("\n"); } while (0)
#define mob_printf(str, ...) do { print_to_uart("MOBVOI[L]: "str, ##__VA_ARGS__); print_to_uart("\n"); } while (0)
//#define mobvoi_warning(...)   do { printf(__VA_ARGS__); puts("\n"); } while (0)
//#define mobvoi_info(...)   do { printf(__VA_ARGS__); puts("\n"); } while (0)
//#define mobvoi_fatal(...)   do { printf(__VA_ARGS__); puts("\n"); } while (0)
//#define mob_printf(...)   do { printf(__VA_ARGS__); puts("\n"); } while (0)

#elif defined(__BES_CORTEX_M4__)
#define mobvoi_warning(...)
#define mobvoi_info(...)
#define mobvoi_fatal(...)
#define mob_printf(...)

#elif defined(__ASDK__)
#define mobvoi_warning(...) do { printf(__VA_ARGS__); printf("\n"); } while (0)
#define mobvoi_info(...)    do { printf(__VA_ARGS__); printf("\n"); } while (0)
#define mobvoi_fatal(...)   do { printf(__VA_ARGS__); printf("\n"); } while (0)
#define mob_printf(...)     do { printf(__VA_ARGS__); printf("\n"); } while (0)

#elif defined(__QUECTEL_ASR_KERNEL__)
#define mobvoi_warning printf
#define mobvoi_info    printf
#define mobvoi_fatal   printf
#define mob_printf     printf

#elif defined(XTENSA_RT600)
int DbgConsole_Printf(const char *fmt_s, ...);
#define mobvoi_warning(str, ...) \
    do { DbgConsole_Printf("MOBVOI[W]: "str, ##__VA_ARGS__); DbgConsole_Printf("\n"); } while (0)
#define mobvoi_info(str, ...) \
    do { DbgConsole_Printf("MOBVOI[I]: "str, ##__VA_ARGS__); DbgConsole_Printf("\n"); } while (0)
#define mobvoi_fatal(str, ...) \
    do { DbgConsole_Printf("MOBVOI[F]: "str, ##__VA_ARGS__); DbgConsole_Printf("\n"); } while (0)
#define mob_printf(str, ...) \
    do { DbgConsole_Printf("MOBVOI[L]: "str, ##__VA_ARGS__); DbgConsole_Printf("\n"); } while (0)
#else
void mobvoi_log(char type, const char* file, int line, const char* fmt, ...);
#define mobvoi_warning(fmt, ...) \
    mobvoi_log('W', __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define mobvoi_info(fmt, ...) \
    mobvoi_log('I', __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define mobvoi_fatal(fmt, ...) \
    mobvoi_log('E', __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
   *(volatile int*) 0 = 0;
#define mob_printf(...) printf(__VA_ARGS__)

#endif

#if defined(MOBVOI_DSP_CHIPSET)
#define mobvoi_assert(cond)
#else
#define mobvoi_assert(cond)                     \
  {                                             \
    if (!(cond)) {                              \
      mobvoi_fatal("assertion failed: " #cond); \
    }                                           \
  }
#endif

#ifdef NR_DEBUG
void mobvoi_memory_stat(const char* tag, int flag);
#endif
void* mobvoi_calloc(int size);
void* mobvoi_realloc(void* ptr, int size);
void mobvoi_free(void* ptr);

#ifdef NR_DEBUG
#define MOBVOI_COPY(dst, src, n) \
  if ((dst < src && dst + n > src) || (src < dst && src + n > dst)) {\
    mobvoi_fatal("Overlap memcpy.");\
  } else {\
    memcpy((dst), (src), (n) * sizeof(*(dst)) + 0 * ((dst) - (src)));\
  }
#else
#define MOBVOI_COPY(dst, src, n) \
  (memcpy((dst), (src), (n) * sizeof(*(dst)) + 0 * ((dst) - (src))))
#endif

#define MOBVOI_MOVE(dst, src, n) \
  (memmove((dst), (src), (n) * sizeof(*(dst)) + 0 * ((dst) - (src))))

#define MOBVOI_MEMSET(dst, value, n) \
  (memset((dst), value, (n) * sizeof(*(dst))))

#define MOBVOI_MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MOBVOI_MAX(a, b) (((a) > (b)) ? (a) : (b))

#define MOBVOI_ASSERT_NEAR_FLOAT(A, B, C) \
    mobvoi_assert(mobvoi_dsp_float_near_equal(A, B, C))
#define MOBVOI_ASSERT_NEAR_SHORT(A, B, C) \
    mobvoi_assert(mobvoi_dsp_short_near_equal(A, B, C))

#ifndef MOBVOI_DSP_CHIPSET
#define MOBVOI_SRAND(x) \
  srand((x))
#else
#define MOBVOI_SRAND(x)
#endif

#ifndef MOB_INT_MAX
#define MOB_INT_MAX ((int) 0x7fffffffUL)
#define MOB_INT_MIN ((int) 0x80000000UL)
#endif

float normalize(int16 value);
int16 denormalize(float value);
int mobvoi_dsp_float_near_equal(mob_float A, mob_float B, mob_float tolerance);
int mobvoi_dsp_short_near_equal(int16 A, int16 B, int16 tolerance);

int mob_get_first_band(int start_freq, mob_float frame_len, int over_sample_ratio);
int mob_get_last_band(int stop_freq, mob_float frame_len, int over_sample_ratio);
int mob_get_band_ceil(mob_float freq, mob_float frame_len, mob_float os);
int mob_get_band_floor(mob_float freq, mob_float frame_len, mob_float os);

int scl_sqrt(int x);
float mob_sqrtf(float x);
float mob_log10f(float x);
float mob_logf(float x);
float mob_sinf(float x);
float mob_cosf(float x);
float mob_powf(float x, float y);

void mobvoi_set_static_memory_base(int idx, void* base, unsigned int total, unsigned int align);
void mobvoi_reset_memory_base(int idx);
void mobvoi_set_shared_memory_base(int idx, void* base, unsigned int total, unsigned int align);
void mobvoi_begin_shared_memory(void);
void mobvoi_end_shared_memory(void);
void mobvoi_set_memory_index(int idx);
void mobvoi_memory_summary(void);

#if defined(__QCC5121__) || defined(MOBVOI_QCC_ON_X86) || defined(ENABLE_FIXED_KWS)
extern int* fft_freq_data;
extern int* fft_tmpbuf_data;
extern int* fft_real;
extern int* fft_imag;
extern int* complexfft_br_buffer;
void init_fft_buffer(void);
void free_fft_buffer(void);
#endif

void* mobvoi_fopen(const char* name, const char* mode);
int mobvoi_fclose(void* p);
uint64 mobvoi_fread(void* buff, uint64 size, uint64 count, void* p);
uint64 mobvoi_fwrite(const void* buff, uint64 size, uint64 count, void* p);

/**
 * Mobvoi dsp get device ID function.
 * @param buffer: memory for storing the device ID.
 * @param len: length of buffer.
 * @return the real length of device ID.
 */
int mobvoi_get_device_id(unsigned char* buffer, int len);

void smooth_3(mob_float* a, mob_float* b, int32 num);
void smooth_5(mob_float* a, mob_float* b, int32 num);

void mobvoi_smooth(mob_float* a, mob_float* b, int32 num, int32 span);

void mobvoi_hann_smooth(mob_float* in, mob_float* out, int32 len, int32 max_hann_taps);

#ifdef __cplusplus
}
#endif

#endif  // SDK_UTILS_OS_SUPPORT_H_
